using System;
using System.Collections.Generic;
using FireStarter.Base;
using FireStarter.CodeGeneration;
using FireStarterModeller.BO;
using NUnit.Framework;

namespace FireStarter.Test.CodeGeneration
{
    [TestFixture]
    public class TestTemplateParser
    {
        [Test]
        public void Test_ExractAllTagReplacements_OneTag()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------
            IDictionary<string, TagReplacement> tagReplacements = templateParser.ExtractAllTagReplacements("SomeText <<firsttag>> some other  text");
            //---------------Execute Test ----------------------
            Assert.AreEqual(1, tagReplacements.Count);
            Assert.AreEqual("<<firsttag>>", tagReplacements["<<firsttag>>"].Tag);
        }

        private static TemplateParser CreateNewTemplateParser()
        {
           return new TemplateParser(new MockClassGenerator("f", "b", "c"));
        }

        [Test]
        public void Test_ExractAllTagReplacements_2Tags()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------
            IDictionary<string, TagReplacement> tagReplacements = templateParser.ExtractAllTagReplacements("SomeText <<firsttag>> some other <<secondtag>> text");
            //---------------Execute Test ----------------------
            Assert.AreEqual(2, tagReplacements.Count);
            Assert.AreEqual("<<firsttag>>", tagReplacements["<<firsttag>>"].Tag);
            Assert.AreEqual("<<secondtag>>", tagReplacements["<<secondtag>>"].Tag);

        }
        [Test]
        public void Test_ExractAllTagReplacements_2Tags_atEndAndBegin()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------
            IDictionary<string, TagReplacement> tagReplacements = templateParser.ExtractAllTagReplacements("<<firsttag>> some other <<secondtag>>");
            //---------------Execute Test ----------------------
            Assert.AreEqual(2, tagReplacements.Count);
        }
        [Test]
        public void Test_ExractAllTagReplacements_NoTags()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------
            IDictionary<string, TagReplacement> tagReplacements = templateParser.ExtractAllTagReplacements("not tags");
            //---------------Execute Test ----------------------
            Assert.AreEqual(0, tagReplacements.Count);
        }
        [Test]
        public void Test_ExtractFirstTagReplacement_InvalidTag_NoContent()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------

            try
            {
                templateParser.ExtractNextTagReplacement("SomeText <<>> some other <<ValidTag>> text", ref pos);
                Assert.Fail("Expected an error");
            }
            //---------------Test Result -----------------------
            catch (TemplateTagException ex)
            {
                StringAssert.Contains("A tag cannot be empty. ie. <<>> is invalid in the template", ex.Message);
            }
            catch (Exception)
            {
                Assert.Fail("TemplateTagException not thrown");
            }
        }

        [Test]
        public void Test_ExtractFirstTagReplacement_InvalidTag_NoEnd()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------

            try
            {
                templateParser.ExtractNextTagReplacement("SomeText <<InvalidTag> some other ", ref pos);
                Assert.Fail("Expected an error");
            }
            //---------------Test Result -----------------------
            catch (TemplateTagException ex)
            {
                StringAssert.Contains
                    ("A tag is not formed correctly. ie. The '<<' of the tag has no corresponding '>>'", ex.Message);
            }
            catch (Exception ex)
            {
                Assert.Fail("TemplateTagException not thrown. Exception that was trown was: " + ex.Message);
            }
        }

        [Test]
        public void Test_ExtractFirstTagReplacement_InvalidTag_NoEnd_WithALaterTag()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------

            try
            {
                templateParser.ExtractNextTagReplacement
                    ("SomeText <<InvalidTag> some other <<ValidTag>> ", ref pos);
                Assert.Fail("Expected an error");
            }
            //---------------Test Result -----------------------
            catch (TemplateTagException ex)
            {
                StringAssert.Contains
                    ("A tag is not formed correctly. ie. The '<<' of the tag has another '<<' before its corresponding '>>'",
                     ex.Message);
            }
            catch (Exception ex)
            {
                Assert.Fail("TemplateTagException not thrown. Exception that was trown was: " + ex.Message);
            }
        }


        [Test]
        public void Test_ExtractFirstTagReplacement_NoTag()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            int pos = -1;
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement("No Tag", ref pos);

            //---------------Test Result -----------------------
            Assert.IsNull(tagReplacement);
        }

        //TODO: Change reading tags to include the << and >> since this will eliminate problems with
        // whitespace

        [Test]
        public void Test_ExtractFirstTagReplacement_ValidTagLast()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            int pos = -1;
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement
                ("SomeText <<ValidTag>>", ref pos);
            //---------------Test Result -----------------------
            AssertValidTag(tagReplacement, "<<ValidTag>>", "My valid replacementValue", "ValidTag");
        }

        [Test]
        public void Test_ExtractFirstTagReplacement_ValidTagMiddle()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            int pos = -1;
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement
                ("SomeText <<ValidTag>> some other text", ref pos);
            //---------------Test Result -----------------------
            AssertValidTag(tagReplacement, "<<ValidTag>>", "My valid replacementValue", "ValidTag");
            Assert.AreEqual(20, pos);
        }

        [Test]
        public void Test_ExtractFirstTagReplacement_ValidTagOnly()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            int pos = -1;
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement("<<ValidTag>>", ref pos);
            //---------------Test Result -----------------------
            AssertValidTag(tagReplacement, "<<ValidTag>>", "My valid replacementValue", "ValidTag");
        }

        [Test]
        public void Test_ExtractSecondTagReplacement_ValidTag_AtEnd()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = 30;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement
                ("SomeText <<FirstTag>> some other text<<ValidTag>>", ref pos);
            //---------------Test Result -----------------------
            AssertValidTag(tagReplacement, "<<ValidTag>>", "My valid replacementValue", "ValidTag");
        }

        [Test]
        public void Test_ExtractSecondTagReplacement_ValidTag_TouchingFirstTag()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            const string templateContents = "SomeText <<FirstTag>><<ValidTag>>";
            templateParser.ExtractNextTagReplacement(templateContents, ref pos);

            //---------------Assert Precondition----------------
            Assert.AreEqual(20, pos);
            //---------------Execute Test ----------------------
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement(templateContents, ref pos);
            //---------------Test Result -----------------------
            AssertValidTag(tagReplacement, "<<ValidTag>>", "My valid replacementValue", "ValidTag");
            Assert.AreEqual(templateContents.Length - 1, pos);
        }

        [Test]
        public void Test_ExtractTagReplacement_ValidTag_WhitespaceAtBegin()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement
                ("SomeText <<    ValidTag>> some other text", ref pos);
            //---------------Test Result -----------------------
            AssertValidTag(tagReplacement, "<<    ValidTag>>", "My valid replacementValue", "ValidTag");
        }

        [Test]
        public void Test_ExtractTagReplacement_ValidTag_WhitespaceAtEnd()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement
                ("SomeText <<ValidTag >> some other text", ref pos);
            //---------------Test Result -----------------------
            AssertValidTag(tagReplacement, "<<ValidTag >>", "My valid replacementValue", "ValidTag");
        }

        [Test]
        public void Test_ExtractTagContent()
        {
            //Tests that the tag contents is correctly extracted from the 
            // tag with all whitespace removed.
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string tagContent = TemplateParser.ExtractTagContent("<<ValidTag>>");

            //---------------Test Result -----------------------
            Assert.AreEqual("ValidTag", tagContent);
        }

        [Test]
        public void Test_ExtractTagContent_OneWhitespaceAtBegin()
        {
            //Tests that the tag contents is correctly extracted from the 
            // tag with all whitespace removed.
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string tagContent = TemplateParser.ExtractTagContent("<< ValidTag>>");

            //---------------Test Result -----------------------
            Assert.AreEqual("ValidTag", tagContent);
        }
        [Test]
        public void Test_ExtractTagContent_WhitespaceAtBegin()
        {
            //Tests that the tag contents is correctly extracted from the 
            // tag with all whitespace removed.
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string tagContent = TemplateParser.ExtractTagContent("<<     ValidTag>>");

            //---------------Test Result -----------------------
            Assert.AreEqual("ValidTag", tagContent);
        }
        [Test]
        public void Test_ExtractTagContent_WhitespaceAtEnd()
        {
            //Tests that the tag contents is correctly extracted from the 
            // tag with all whitespace removed.
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string tagContent = TemplateParser.ExtractTagContent("<<ValidTag >>");

            //---------------Test Result -----------------------
            Assert.AreEqual("ValidTag", tagContent);
        }
        [Test]
        public void Test_ExtractTagContent_WhitespaceinMiddle()
        {
            //Tests that the tag contents is correctly extracted from the 
            // tag with all whitespace removed.
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            string tagContent = TemplateParser.ExtractTagContent("<<Valid Tag>>");

            //---------------Test Result -----------------------
            Assert.AreEqual("Valid Tag", tagContent);
        }

        #region Foreach Template

        [Test]
        public void Test_ExtractCollectionName()
        {
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string foreachCollectionName = TemplateParser.ExtractForEachCollectionName("FOREACH(collectionName):dosomething");
            //---------------Test Result -----------------------
            Assert.AreEqual("collectionName",foreachCollectionName);
        }
        [Test]
        public void Test_ExtractCollectionName_whitespace()
        {
            //---------------Set up test pack-------------------
            
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string foreachCollectionName = TemplateParser.ExtractForEachCollectionName("FOREACH (collectionName):dosomething");
            //---------------Test Result -----------------------
            Assert.AreEqual("collectionName",foreachCollectionName);
        }

        [Test]
        public void Test_ExtractForEachTagReplacement()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement
                ("SomeText <<FOREACH (collectionName):dosomething>> some other text", ref pos);
            //---------------Test Result -----------------------
            ForEachReplacement replacement = (ForEachReplacement) tagReplacement.Replacement;
            Assert.IsNotNull(replacement.Replacement);
//            Assert.AreEqual("collectionName", replacement.CollectionName);
        }
        [Test]
        public void Test_ExtractForEachTagReplacement_nowhitespace()
        {
            //---------------Set up test pack-------------------
            TemplateParser templateParser = CreateNewTemplateParser();
            int pos = -1;
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            TagReplacement tagReplacement = templateParser.ExtractNextTagReplacement
                ("SomeText <<FOREACH(collectionName2):dosomething>> some other text", ref pos);
            //---------------Test Result -----------------------
            ForEachReplacement replacement = (ForEachReplacement)tagReplacement.Replacement;
//            Assert.AreEqual("collectionName2", replacement.CollectionName);
        }
        #endregion



        private static void AssertValidTag(TagReplacement tagReplacement, string expectedTagName, string expectedTagReplacementContent, string expectedTagContent)
        {

            Assert.IsNotNull(tagReplacement);
            Assert.AreEqual(expectedTagName, tagReplacement.Tag);
            Assert.IsInstanceOf(typeof(ValueReplacement_old), tagReplacement.Replacement);
//            Assert.AreEqual(expectedTagReplacementContent, tagReplacement.Replacement.ReplacementString);
        }
    }

    internal class MockClassGenerator : ClassGenerator
    {
        public MockClassGenerator(string className, string projectName, string projectPath) : base(className, projectName, projectPath)
        {
        }

        public override void Compile()
        {
           
        }

        public override void GenerateCode()
        {
            
        }

        public override string GetValueReplacementContent(string tagContent)
        {
            return "My valid replacementValue";
        }

        public override IList<IModelClass> GetModelElementsCollection(string tagContent)
        {
            return new List<IModelClass>();
        }
    }
}
